//
//  BonjourListener.m
//  Mini Cidney
//
//  Created by Chris Karr on 1/13/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "BonjourListener.h"
#import <AddressBook/AddressBook.h>
#import "Caller.h"
#import "Dispatcher.h"

#define PORT 31264
#define SERVICE @"_cidney._tcp."

@implementation BonjourListener

@synthesize connection;
@synthesize port;
@synthesize bonjour;
@synthesize name;
@synthesize number;
@synthesize imageData;

- (NSString *) normalizePhoneNumber:(NSString *) phoneNumber
{
	NSMutableString * newNumber = [NSMutableString stringWithString:phoneNumber];
	
	[newNumber replaceOccurrencesOfString:@"\r" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	[newNumber replaceOccurrencesOfString:@"\n" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	[newNumber replaceOccurrencesOfString:@"-" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	[newNumber replaceOccurrencesOfString:@" " withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	[newNumber replaceOccurrencesOfString:@"(" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	[newNumber replaceOccurrencesOfString:@")" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	[newNumber replaceOccurrencesOfString:@"+" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [newNumber length])];
	
	return newNumber;
}

- (ABPerson *) findPersonByNumber:(NSString *) phoneNumber
{
	number = [self normalizePhoneNumber:phoneNumber];
	
	ABAddressBook * ab = [ABAddressBook sharedAddressBook];
				
	for (ABPerson * person in [ab people])
	{
		ABMutableMultiValue * phones = [person valueForProperty:kABPhoneProperty];
		
		int i = 0;
		for (i = 0; i < [phones count]; i++)
		{
			NSString * phone = [self normalizePhoneNumber:[phones valueAtIndex:i]];
		
			if ([phone rangeOfString:phoneNumber].location != NSNotFound)
				return person;
		}
	}
	
	return nil;
}

- (NSString *) machineName
{
	CFStringRef nameRef;
	NSString * computerName;
	nameRef = CSCopyMachineName ();
	computerName = [NSString stringWithString:(NSString *) nameRef];
	CFRelease (nameRef);

	return computerName;
}

- (void) stopServer
{
	[self.connection release];
	self.connection = nil;

	[self.port release];
	self.port = nil;

	[self.bonjour release];
	self.bonjour = nil;
}

- (void) startServer
{
	if (self.connection != nil || self.port != nil || self.bonjour != nil)
		[self stopServer];
	
	self.port = [[NSSocketPort alloc] initWithTCPPort:PORT];
    self.connection = [[NSConnection alloc] initWithReceivePort:port sendPort:nil];
    [self.connection setRootObject:self];
	
	self.bonjour = [[NSNetService alloc] initWithDomain:@"local" type:SERVICE name:[self machineName] port:PORT];
	[self.bonjour publish];
}

- (void) awakeFromNib
{
	NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
	
	if ([defaults boolForKey:@"Bonjour Listener"])
		[self startServer];
		
	[defaults addObserver:self forKeyPath:@"Bonjour Listener" options:NSKeyValueObservingOptionNew context:NULL];
}

- (void) observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context
{
	NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
	
	if ([defaults boolForKey:@"Bonjour Listener"])
		[self startServer];
	else
		[self stopServer];
}


- (NSString *) incomingCaller:(NSString *) newName number:(NSString *) newNumber image:(NSData *) newImageData
{
	ABPerson * person = [self findPersonByNumber:newNumber];

	Caller * dict = [Caller dictionary];
	
	[dict setValue:newName forKey:NAME_KEY];
	[dict setValue:newNumber forKey:NUMBER_KEY];
	[dict setValue:person forKey:PERSON_KEY];
	[dict setValue:[NSNumber numberWithBool:YES] forKey:BONJOUR_KEY];

	[[NSNotificationCenter defaultCenter] postNotificationName:INCOMING_CALL object:self userInfo:dict];

	return @"ok";
}

@end
